package com.zwh.se.io.net.tcp;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author zwh
 * 从先需要启动服务器才能正常处理请求信息这点可以得知在TCP的之间客户端和服务端之间的地位是不同等的(服务器必须开着并一直进行请求才可以)
 */
public class SocketServer {

    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = null;
        Socket socket = null;

        try{
            //创建一个服务端对象(ServerSocket)
            serverSocket = new ServerSocket(6666);
            //死循环,让服务器一直监听客户端是否发送数据
            while (true){
                //监听客户端的连接,获取和客户端通信的Socket对象
                //此方法调用后会直接堵塞(堵塞方法),直至有监听到socket对象有数据后才会继续执行后续逻辑(当接收到socket后,就可以认为客户端与服务端产生了连接)
                socket = serverSocket.accept();
                //优化模型(指通过多线程处理):不做优化的话,也就是不开多线程,功能一样可以生效,但是理解一下就可以知道,这样相当于在
                //   accept()调用之后堵塞,然后处理完所有客户端的信息并返回之后,才能够再次accept()继续监听,这样效率就被浪费了,所以采用多线程来处理
                System.out.println("ip:" +socket.getInetAddress().getHostAddress() +"已连接");
                new ServerThread(socket).start();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            socket.close();
            serverSocket.close();
        }
    }
    static class ServerThread extends Thread{

        InputStream inputStream = null;
        BufferedReader bufferedReader = null;
        OutputStream outputStream = null;
        Socket acceptSocket = null;
        DataInputStream dataInputStream = null;

        public ServerThread(Socket socket) {
            acceptSocket = socket;
        }
        private void lookSocketState(Socket socket){
            //查看socket状态
            System.out.println("socket.isInputShutdown() = " + socket.isInputShutdown());
            System.out.println("socket.isBound() = " + socket.isBound()); //如果Socket已经与本地的一个端口绑定，返回true，否则返回false
            System.out.println("socket.isClosed() = " + socket.isClosed());//根据连接是否关闭返回一个boolean值，关闭则返回true，否则返回false
            System.out.println("socket.isConnected() = " + socket.isConnected());//如果连接是否曾被连接过则返回true，否则返回false
            System.out.println("socket.isOutputShutdown() = " + socket.isOutputShutdown());
        }
        @Override
        public void run() {
            try{
                //先查看下socket状态,以方便理解之后的shutdownInput和shutdownOutput
                lookSocketState(acceptSocket);
                //从Socket获取输入流,接收服务器发送的数据
                inputStream = acceptSocket.getInputStream();
                //为了方便直接使用缓冲流阅读了,如果不懂相关知识请先去补充IO知识
                dataInputStream = new DataInputStream(inputStream);
                bufferedReader = new BufferedReader(new InputStreamReader(dataInputStream));
                String msg = bufferedReader.readLine();
                if (msg != null){
                    //对数据进行操作
                    System.out.println(msg);
                    msg = bufferedReader.readLine();
                }
                //调用Socket对象的shutdownInput方法通知客户端数据接收完毕
                acceptSocket.shutdownInput();
                System.out.println("acceptSocket.isInputShutdown() = " + acceptSocket.isInputShutdown());
                //从Socket中拿到输出流往客户端发送数据
                outputStream = acceptSocket.getOutputStream();
//                outputStream.write("服务器已接收到客户端信息,over".getBytes(StandardCharsets.UTF_8));
                BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
                bufferedWriter.write("接收完毕");
                bufferedWriter.close();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                //关闭流+关闭Socket对象(关闭网络资源)
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (bufferedReader != null) {
                        bufferedReader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (outputStream != null) {
                        outputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (acceptSocket != null) {
                        acceptSocket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (dataInputStream != null) {
                        dataInputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        }
    }
}
